package com.example.deepseek.service.impl;

import com.example.deepseek.config.DeepseekConfig;
import com.example.deepseek.model.*;
import com.example.deepseek.service.ChatSessionService;
import com.example.deepseek.service.DeepseekService;
import com.example.deepseek.service.PdfProcessingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class DeepseekServiceImpl implements DeepseekService {

    private final RestTemplate restTemplate;
    private final DeepseekConfig deepseekConfig;
    private final SimpMessagingTemplate messagingTemplate;
    private final ChatSessionService chatSessionService;
    private final PdfProcessingService pdfProcessingService;

    @Override
    public ChatSession createChatSession(String name) {
        // 使用服务创建会话并持久化
        return chatSessionService.createSession(name);
    }

    @Override
    public List<ChatSession> getAllSessions() {
        // 从数据库获取所有会话
        return chatSessionService.getAllSessions();
    }

    @Override
    public ChatSession getSession(String sessionId) {
        // 从数据库获取会话
        return chatSessionService.getSession(sessionId);
    }

    @Override
    public void updateSession(ChatSession session) {
        // 这个方法可能需要添加到ChatSessionService
        // 临时实现可以是删除旧会话然后创建新会话
        if (session != null) {
            // 保存会话的消息
            List<Message> messages = new ArrayList<>(session.getMessages());

            // 清空会话的消息（避免重复添加）
            session.getMessages().clear();

            // 更新会话基本信息
            ChatSession updatedSession = chatSessionService.createSession(session.getName());
            updatedSession.setId(session.getId());

            // 重新添加消息
            for (Message message : messages) {
                chatSessionService.addMessage(updatedSession.getId(), message);
            }
        }
    }

    @Override
    public void clearSession(String sessionId) {
        chatSessionService.clearMessages(sessionId);
    }

    @Override
    public void deleteSession(String sessionId) {
        chatSessionService.deleteSession(sessionId);
    }

    @Override
    @Async
    public CompletableFuture<Message> sendMessage(String sessionId, String message) {
        ChatSession session = getSession(sessionId);
        if (session == null) {
            throw new IllegalArgumentException("聊天会话不存在: " + sessionId);
        }

        // 创建用户消息
        Message userMessage = new Message("user", message);

        // 持久化用户消息到数据库
        chatSessionService.addMessage(sessionId, userMessage);

        // 也添加到会话对象中用于API调用
        session.addMessage(userMessage);

        // 发送消息到DeepSeek API
        try {
            ChatRequest request = new ChatRequest();
            request.setModel(deepseekConfig.getModel());

            // 准备消息列表
            List<Message> apiMessages = new ArrayList<>();

            // 检查会话中是否有文件上下文
            List<Message> fileMessages = findFileMessagesInSession(session);

            // 如果有文件上下文，添加系统提示
            if (!fileMessages.isEmpty()) {
                // 创建系统提示，引导AI参考上传的文件
                StringBuilder systemPrompt = new StringBuilder();
                systemPrompt.append("用户已上传以下文件，请根据这些文件内容回答问题：\n\n");

                for (Message fileMsg : fileMessages) {
                    systemPrompt.append("- 文件名: ").append(fileMsg.getFileName()).append("\n");

                    // 添加全部文件内容（如果存在）- 优先使用文本内容
                    if (fileMsg.getTextContent() != null && !fileMsg.getTextContent().isEmpty()) {
                        systemPrompt.append("文件内容:\n").append(fileMsg.getTextContent()).append("\n\n");
                    } else if (fileMsg.getFileContent() != null && fileMsg.getFileContent().length > 0) {
                        try {
                            // 尝试将二进制内容转换为文本
                            String content = new String(fileMsg.getFileContent(), "UTF-8");
                            systemPrompt.append("文件内容:\n").append(content).append("\n\n");
                        } catch (Exception e) {
                            systemPrompt.append("(文件内容为二进制数据，无法显示)\n\n");
                        }
                    } else {
                        systemPrompt.append("(文件内容为空或无法读取)\n\n");
                    }
                }

                // 添加系统提示
                apiMessages.add(new Message("system", systemPrompt.toString()));
                log.info("添加包含文件内容的系统提示，长度: {}", systemPrompt.length());
            }

            // 添加交互式对话历史（用户和助手的消息）
            String lastRole = null;
            for (Message msg : session.getMessages()) {
                // 只选取用户和助手的消息，跳过系统消息
                if (("user".equals(msg.getRole()) || "assistant".equals(msg.getRole()))) {
                    // 避免连续添加相同角色的消息
                    if (!msg.getRole().equals(lastRole)) {
                        apiMessages.add(msg);
                        lastRole = msg.getRole();
                    } else {
                        // 如果连续两条相同角色，则用新消息替换上一条
                        apiMessages.set(apiMessages.size() - 1, msg);
                    }
                }
            }

            // 确保交互历史以用户消息结束
            if (!"user".equals(lastRole) && apiMessages.size() > 0) {
                apiMessages.remove(apiMessages.size() - 1);
            }

            // 打印消息列表，用于调试
            log.info("即将发送 {} 条消息给DeepSeek API", apiMessages.size());
            for (int i = 0; i < apiMessages.size(); i++) {
                Message msg = apiMessages.get(i);
                log.info("消息 {}: 角色 = {}, 内容长度 = {}",
                        i + 1, msg.getRole(), msg.getContent().length());
            }

            request.setMessages(apiMessages);
            request.setTemperature(0.7);
            request.setMax_tokens(2000);
            request.setStream(false);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + deepseekConfig.getApiKey());

            HttpEntity<ChatRequest> entity = new HttpEntity<>(request, headers);

            // 调用DeepSeek API
            log.info("开始调用DeepSeek API");
            ChatResponse response = restTemplate.postForObject(
                    deepseekConfig.getApiUrl(),
                    entity,
                    ChatResponse.class
            );
            log.info("DeepSeek API调用完成");

            if (response != null && !response.getChoices().isEmpty()) {
                Message assistantMessage = response.getChoices().get(0).getMessage();
                log.info("接收到DeepSeek回复，长度: {} 字符", assistantMessage.getContent().length());

                // 持久化助手消息到数据库
                chatSessionService.addMessage(sessionId, assistantMessage);

                // 也添加到会话对象中
                session.addMessage(assistantMessage);

                // 发送消息到WebSocket客户端
                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, assistantMessage);

                return CompletableFuture.completedFuture(assistantMessage);
            } else {
                log.error("DeepSeek API返回空响应");
                Message errorMessage = new Message("assistant", "抱歉，我无法处理您的请求。");

                // 持久化错误消息
                chatSessionService.addMessage(sessionId, errorMessage);

                // 添加到会话
                session.addMessage(errorMessage);

                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
                return CompletableFuture.completedFuture(errorMessage);
            }
        } catch (Exception e) {
            log.error("调用DeepSeek API时出错", e);
            Message errorMessage = new Message("assistant", "抱歉，发生错误: " + e.getMessage());

            // 持久化错误消息
            chatSessionService.addMessage(sessionId, errorMessage);

            // 添加到会话
            session.addMessage(errorMessage);

            messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
            return CompletableFuture.completedFuture(errorMessage);
        }
    }


    @Override
    @Async
    public CompletableFuture<Message> analyzeFileContent(String sessionId, String fileContent, String fileName) {
        ChatSession session = getSession(sessionId);
        if (session == null) {
            throw new IllegalArgumentException("聊天会话不存在: " + sessionId);
        }

        try {
            // 创建系统消息
            String systemPrompt;

            // 如果是PDF文件，尝试使用文档检索增强
            if (fileName.toLowerCase().endsWith(".pdf")) {
                // 查询相关文档片段
                List<DocumentChunk> relevantChunks = pdfProcessingService.searchRelevantChunks(fileContent, 5);

                if (!relevantChunks.isEmpty()) {
                    // 构建包含相关文档上下文的提示词
                    StringBuilder contextBuilder = new StringBuilder();
                    contextBuilder.append("以下是从向量数据库中检索到的相关文档片段：\n\n");

                    for (int i = 0; i < relevantChunks.size(); i++) {
                        DocumentChunk chunk = relevantChunks.get(i);
                        contextBuilder.append("文档 ").append(i + 1).append("：\n");
                        contextBuilder.append(chunk.getContent()).append("\n\n");
                    }

                    systemPrompt = "你现在需要分析一个上传的PDF文件。文件名：" + fileName +
                            "。请详细分析文件内容，提取关键信息，并提供有价值的见解。\n\n" +
                            "相关的文档上下文:\n" + contextBuilder.toString();
                } else {
                    systemPrompt = "你现在需要分析一个上传的PDF文件。文件名：" + fileName +
                            "。请详细分析文件内容，提取关键信息，并提供有价值的见解。";
                }
            } else {
                systemPrompt = "你现在需要分析一个上传的文件。文件名：" + fileName +
                        "。请详细分析文件内容，提取关键信息，并提供有价值的见解。";
            }

            // 构建请求
            ChatRequest request = new ChatRequest();
            request.setModel(deepseekConfig.getModel());

            // 创建消息列表
            List<Message> messages = new ArrayList<>();
            messages.add(new Message("system", systemPrompt));

            // 添加文件内容作为用户消息
            String userPrompt = "这是文件的内容，请分析并回答：\n\n" + fileContent;
            messages.add(new Message("user", userPrompt));

            request.setMessages(messages);
            request.setTemperature(0.5);
            request.setMax_tokens(4000);
            request.setStream(false);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + deepseekConfig.getApiKey());

            HttpEntity<ChatRequest> entity = new HttpEntity<>(request, headers);

            // 调用DeepSeek API
            ChatResponse response = restTemplate.postForObject(
                    deepseekConfig.getApiUrl(),
                    entity,
                    ChatResponse.class
            );

            if (response != null && !response.getChoices().isEmpty()) {
                Message assistantMessage = response.getChoices().get(0).getMessage();
                assistantMessage.setContent("**文件分析结果**\n\n" + assistantMessage.getContent());

                // 持久化助手消息到数据库
                chatSessionService.addMessage(sessionId, assistantMessage);

                // 也添加到会话对象中
                session.addMessage(assistantMessage);

                // 发送消息到WebSocket客户端
                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, assistantMessage);

                return CompletableFuture.completedFuture(assistantMessage);
            } else {
                log.error("DeepSeek API返回空响应");
                Message errorMessage = new Message("assistant", "抱歉，我无法分析这个文件。");

                // 持久化错误消息
                chatSessionService.addMessage(sessionId, errorMessage);
                session.addMessage(errorMessage);
                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
                return CompletableFuture.completedFuture(errorMessage);
            }
        } catch (Exception e) {
            log.error("文件分析出错", e);
            Message errorMessage = new Message("assistant", "文件分析过程中出错: " + e.getMessage());

            // 持久化错误消息
            chatSessionService.addMessage(sessionId, errorMessage);
            session.addMessage(errorMessage);
            messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
            return CompletableFuture.completedFuture(errorMessage);
        }
    }

    // 添加新方法，构建对话历史
    private List<Message> buildDialogueHistory(ChatSession session) {
        List<Message> dialogMessages = new ArrayList<>();
        String lastRole = null;

        // 提取用户和助手的消息，确保它们交替出现
        for (Message msg : session.getMessages()) {
            if ("user".equals(msg.getRole()) || "assistant".equals(msg.getRole())) {
                // 避免连续添加相同角色的消息
                if (!msg.getRole().equals(lastRole)) {
                    dialogMessages.add(msg);
                    lastRole = msg.getRole();
                } else {
                    // 如果遇到连续相同角色的消息，替换之前的同角色消息
                    // 这样可以保留最新的消息内容
                    dialogMessages.set(dialogMessages.size() - 1, msg);
                }
            }
        }

        // 确保最后一条消息是用户消息
        if (!"user".equals(lastRole) && !dialogMessages.isEmpty()) {
            dialogMessages.remove(dialogMessages.size() - 1);
        }

        return dialogMessages;
    }

    // 添加错误处理方法
    private void handleErrorMessage(String sessionId, ChatSession session, Message errorMessage) {
        // 持久化错误消息
        chatSessionService.addMessage(sessionId, errorMessage);

        // 添加到会话
        session.addMessage(errorMessage);

        // 发送到WebSocket
        messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
    }

    @Override
    @Async
    public CompletableFuture<Message> analyzeMultipleFiles(String sessionId, String combinedContent, int fileCount) {
        ChatSession session = getSession(sessionId);
        if (session == null) {
            throw new IllegalArgumentException("聊天会话不存在: " + sessionId);
        }

        try {
            // 创建系统消息，指导AI如何处理文件
            String systemPrompt = "你现在需要分析" + fileCount + "个上传的文件。请详细分析所有文件内容，提取关键信息，并提供有价值的见解。";

            // 构建请求
            ChatRequest request = new ChatRequest();
            request.setModel(deepseekConfig.getModel());

            // 创建消息列表
            List<Message> messages = new ArrayList<>();

            // 先添加系统消息作为指导
            messages.add(new Message("system", systemPrompt));

            // 添加文件内容作为用户消息
            String userPrompt = "这是" + fileCount + "个文件的内容，请分析并回答：\n\n" + combinedContent;
            messages.add(new Message("user", userPrompt));

            request.setMessages(messages);
            request.setTemperature(0.5); // 可以调整，使结果更精确
            request.setMax_tokens(4000); // 增加token数以容纳更长的分析
            request.setStream(false);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + deepseekConfig.getApiKey());

            HttpEntity<ChatRequest> entity = new HttpEntity<>(request, headers);

            // 调用DeepSeek API
            ChatResponse response = restTemplate.postForObject(
                    deepseekConfig.getApiUrl(),
                    entity,
                    ChatResponse.class
            );

            if (response != null && !response.getChoices().isEmpty()) {
                Message assistantMessage = response.getChoices().get(0).getMessage();
                assistantMessage.setContent("**多文件分析结果**\n\n" + assistantMessage.getContent());

                // 持久化助手消息到数据库
                chatSessionService.addMessage(sessionId, assistantMessage);

                // 也添加到会话对象中
                session.addMessage(assistantMessage);

                // 发送消息到WebSocket客户端
                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, assistantMessage);

                return CompletableFuture.completedFuture(assistantMessage);
            } else {
                log.error("DeepSeek API返回空响应");
                Message errorMessage = new Message("assistant", "抱歉，我无法分析这些文件。");

                // 持久化错误消息
                chatSessionService.addMessage(sessionId, errorMessage);
                session.addMessage(errorMessage);
                messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
                return CompletableFuture.completedFuture(errorMessage);
            }
        } catch (Exception e) {
            log.error("文件分析出错", e);
            Message errorMessage = new Message("assistant", "文件分析过程中出错: " + e.getMessage());

            // 持久化错误消息
            chatSessionService.addMessage(sessionId, errorMessage);
            session.addMessage(errorMessage);
            messagingTemplate.convertAndSend("/topic/chat/" + sessionId, errorMessage);
            return CompletableFuture.completedFuture(errorMessage);
        }
    }

    @Override
    public void sendWebSocketMessage(String sessionId, Message message) {
        messagingTemplate.convertAndSend("/topic/chat/" + sessionId, message);
    }


    /**
     * 从会话中查找包含文件内容的系统消息
     */
    private List<Message> findFileMessagesInSession(ChatSession session) {
        List<Message> fileMessages = session.getMessages().stream()
                // 修改过滤条件，确保正确识别system角色的文件消息
                .filter(msg -> "system".equals(msg.getRole()) && msg.getFileName() != null)
                .collect(Collectors.toList());

        log.info("在会话中找到 {} 条包含文件内容的消息", fileMessages.size());
        if (!fileMessages.isEmpty()) {
            for (Message msg : fileMessages) {
                // 检查是否有文本内容
                String content = msg.getTextContent() != null ? msg.getTextContent() :
                        (msg.getFileContent() != null ? "二进制内容" : "无内容");
                log.info("文件消息: 文件名={}, 内容类型={}, 内容长度={}",
                        msg.getFileName(),
                        msg.getTextContent() != null ? "文本" : "二进制",
                        content != null ? (content.equals("二进制内容") ? "二进制" : content.length()) : 0);
            }
        }
        return fileMessages;
    }
}